Handle `rev` being a `tag`
authorAlex Crichton <alex@alexcrichton.com>
Mon, 23 Jan 2017 17:25:14 +0000 (09:25 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 23 Jan 2017 17:25:14 +0000 (09:25 -0800)
Previously if a rev was specified as a tag then we'd trip an assertion because
resetting to that tag would reset to the tag that the commit pointed to, which
would then cause the head id of the repo to be different than what we thought it
was.

Instead, we handle the case where a `rev` specification is a tag explicitly by
using the tag's target id as the revision that we're going to check out, not the
id of the tag itself.

Closes #3580

src/cargo/sources/git/utils.rs
tests/git.rs

index 3b3b005f3a03baec770160f878c838ae947c3f80..03fe6a5e2f9f2bd35efc602cff82d97d0a1d8995 100644 (file)
@@ -217,7 +217,10 @@ impl GitDatabase {
             }
             GitReference::Rev(ref s) => {
                 let obj = self.repo.revparse_single(s)?;
-                obj.id()
+                match obj.as_tag() {
+                    Some(tag) => tag.target_id(),
+                    None => obj.id(),
+                }
             }
         };
         Ok(GitRevision(id))
index f56c67fea556ea3f098d3497f270cee157d4cab9..e1aff724050f2c9173c5bc93376bcce180b642e9 100644 (file)
@@ -1826,3 +1826,48 @@ fn add_a_git_dep() {
 
     assert_that(p.cargo("build"), execs().with_status(0));
 }
+
+#[test]
+fn two_at_rev_instead_of_tag() {
+    let git = git::new("git", |p| {
+        p.file("Cargo.toml", r#"
+            [project]
+            name = "git1"
+            version = "0.5.0"
+            authors = []
+        "#)
+        .file("src/lib.rs", "")
+        .file("a/Cargo.toml", r#"
+            [project]
+            name = "git2"
+            version = "0.5.0"
+            authors = []
+        "#)
+        .file("a/src/lib.rs", "")
+    }).unwrap();
+
+    // Make a tag corresponding to the current HEAD
+    let repo = git2::Repository::open(&git.root()).unwrap();
+    let head = repo.head().unwrap().target().unwrap();
+    repo.tag("v0.1.0",
+             &repo.find_object(head, None).unwrap(),
+             &repo.signature().unwrap(),
+             "make a new tag",
+             false).unwrap();
+
+    let p = project("foo")
+        .file("Cargo.toml", &format!(r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            git1 = {{ git = '{0}', rev = 'v0.1.0' }}
+            git2 = {{ git = '{0}', rev = 'v0.1.0' }}
+        "#, git.url()))
+        .file("src/lib.rs", "");
+
+    assert_that(p.cargo_process("generate-lockfile"), execs().with_status(0));
+    assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+}